package com.example.mykotlin.base.result

import cn.dev33.satoken.exception.NotLoginException
import cn.dev33.satoken.exception.SaTokenException
import jakarta.validation.ConstraintViolationException
import jakarta.validation.ValidationException
import org.hibernate.validator.internal.engine.path.PathImpl
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.validation.BindException
import org.springframework.validation.FieldError
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice


@RestControllerAdvice
class MyResultControllerAdvice {
    companion object {
        private val LOG: Logger = LoggerFactory.getLogger(R.Companion::class.java)
    }

    @ExceptionHandler(Exception::class)
    fun exHandler(ex: Exception): R<Any> {
        LOG.error("异常:", ex)
        return R.fail(msg = "异常:${ex.javaClass.simpleName}")
    }

    @ExceptionHandler(ValidationException::class)
    fun vexHandler(vex: ValidationException): R<Any> {
        val msg = if (vex is ConstraintViolationException) vex.constraintViolations.map {
            val propertyPath = it.propertyPath
            "${if (propertyPath is PathImpl) "[${propertyPath.leafNode.asString()}]" else ""}${it.message}"
        }.reduce { acc, next -> "$acc,$next" }
        else "异常:${vex.localizedMessage}"
        LOG.error("异常:{}", msg)
        return R.fail(msg = msg)
    }

    @ExceptionHandler(BindException::class)
    fun bexHandler(bex: BindException): R<Any> {
        LOG.error("参数异常:", bex)
        return R.fail(msg = bex.allErrors.map { "${if (it is FieldError) "[${it.field}]" else ""}${it.defaultMessage}" }
            .reduce { acc, next -> "$acc,$next" })
    }

    @ExceptionHandler(ServiceException::class)
    fun sexHandler(sex: ServiceException): R<Any> {
        LOG.warn("服务请求成功，业务异常:", sex)
        return R.fail(code = sex.code, msg = sex.message ?: "服务请求成功，业务异常")
    }

    @ExceptionHandler(SaTokenException::class)
    fun stxHandler(stex: SaTokenException): R<Any> {
        LOG.warn("用户认证信息异常:", stex)
        return R.fail(code = "403", msg = stex.message ?: "用户认证信息有误")
    }

    @ExceptionHandler(NotLoginException::class)
    fun stxHandler(nlex: NotLoginException): R<Any> {
        LOG.warn("服务请求成功，业务异常:", nlex)
        return R.fail(code = "404", msg = "用户未登录")
    }
}